using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TankWars
{
    public class TankManager
    {
        /// <summary>
        /// Holds all players and tanks
        /// </summary>
        public Dictionary<Player, Tank> dicTanks = new Dictionary<Player, Tank>();

        private Dictionary<Type, Texture2D> dicShotTextures = new Dictionary<Type, Texture2D>();
        private Dictionary<Type, Texture2D> dicShotIcons = new Dictionary<Type, Texture2D>();
        private Texture2D tankSprite;
        private Texture2D turretSprite;
        private SpriteBatch spriteBatch;

        /// <summary>
        /// Creates a new tankmanager
        /// </summary>
        /// <param name="TankSprite"></param>
        /// <param name="spriteBatch"></param>
        public TankManager(Texture2D TankSprite, Texture2D TankTurretSprite, Dictionary<Type, Texture2D> shotTextures, Dictionary<Type, Texture2D> shotIcons,  SpriteBatch spriteBatch)
        {
            this.tankSprite = TankSprite;
            this.turretSprite = TankTurretSprite;

            this.dicShotTextures = shotTextures;
            this.dicShotIcons = shotIcons;

            this.spriteBatch = spriteBatch;
        }

        /// <summary>
        /// Creates a new tank for the given player
        /// </summary>
        /// <param name="player">Player the tank belongs to</param>
        public void NewTank(Player player)
        {
            this.dicTanks.Add(player, new Tank(this.tankSprite, this.turretSprite ,player, this.dicShotTextures, this.dicShotIcons));
        }

        /// <summary>
        /// Creates a new tank for the given player with the given color
        /// </summary>
        /// <param name="player">Player the tank belongs to</param>
        /// <param name="tankColor">Color of the tank</param>
        public void NewTank(Player player, Color tankColor)
        {
            this.dicTanks.Add(player, new Tank(this.tankSprite, this.turretSprite, tankColor, player, this.dicShotTextures, this.dicShotIcons));
        }

        /// <summary>
        /// Draws all tanks
        /// </summary>
        /// <param name="map">Game map</param>
        public void Draw(Map map)
        {
            this.spriteBatch.Begin();
            foreach (KeyValuePair<Player, Tank> CurrentPlayerTank in this.dicTanks)
            {
                Tank currentTank = CurrentPlayerTank.Value;
                currentTank.Draw(this.spriteBatch, map);
            }
            this.spriteBatch.End();
        }

        /// <summary>
        /// Updates the position of all tanks
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime, Microsoft.Xna.Framework.Input.MouseState mousestate, Map map)
        {
            foreach (KeyValuePair<Player, Tank> currentPlayerTank in this.dicTanks)
            {
                currentPlayerTank.Value.UpdatePosition(gameTime, mousestate, map);
            }
        }

        /// <summary>
        /// Checks for collisions between a tank and the game field.
        /// </summary>
        public void checkFieldCollisions(GameField field)
        {
            if (this.dicTanks.Count > 1)
            {
                foreach (KeyValuePair<Player, Tank> currentPlayerTank in this.dicTanks)
                {
                    Tank tank = currentPlayerTank.Value;

                    //Convert the tank's coordinates into field matrix coordinates.
                    int fieldX = (int)(tank.vPosition.X/field.blockSize + .5);
                    int fieldY = (int)(tank.vPosition.Y/field.blockSize + .5);

                    //Number of blocks the tank collided with.
                    int numberOfCollisions = 0;

                    //Did the tank hit a block from a diangle?
                    //-1 if false, otherwise contains the collide angle.
                    double diangleHit = -1;

                    //Cycle through the field positions that should be checked.
                    for (int x = fieldX-2; x <= fieldX+2; x++)
                    for (int y = fieldY-2; y <= fieldY+2; y++)
                    {
                        //If a block is at the location.
                        if (field.occupied(x,y))
                        {
                            //If the tank collided with a block.
                            if (tank.tankCollide(x*field.blockSize,y*field.blockSize,field.blockSize,field.blockSize))
                            {
                                //Increment number of collisions.
                                numberOfCollisions++;

                                //Get collide angle.
                                double collideAngle = tank.collideAngle(x * field.blockSize, y * field.blockSize, field.blockSize, field.blockSize);

                                //Vertical collision
                                if ((collideAngle > 47 && collideAngle < 123) || (collideAngle < 313 && collideAngle > 227))
                                {
                                    tank.handleYCollision();
                                }
                                //Horizontal collision
                                else if ((collideAngle < 43 || collideAngle > 317) || (collideAngle < 223 && collideAngle > 137))
                                {
                                    tank.handleXCollision();
                                }
                                else//Diangle collision.
                                {
                                   diangleHit = collideAngle;
                                }
                            }//If: tank Collided.
                        }//If: field Occupied
                    }//For:cycle through all field positions.

                    //Do this check for a collision on a block corner.
                    //Only is checked if a single block was hit at a diangle.
                    if ((numberOfCollisions == 1) && (diangleHit > 0))
                    {
                        //First quad
                        if ((diangleHit > 0) && (diangleHit < 90))
                        {
                            if (tank.vSpeed.X > 0)
                                tank.handleXCollision();
                            if (tank.vSpeed.Y < 0)
                                tank.handleYCollision();
                        }
                        //Second quad
                        else if ((diangleHit > 90) && (diangleHit < 180))
                        {
                            if (tank.vSpeed.X < 0)
                                tank.handleXCollision();
                            if (tank.vSpeed.Y < 0)
                                tank.handleYCollision();
                        }
                        //Third quad
                        else if ((diangleHit > 180) && (diangleHit < 270))
                        {
                           if (tank.vSpeed.X < 0)
                                tank.handleXCollision();
                            if (tank.vSpeed.Y > 0)
                                tank.handleYCollision();
                        }
                        //Forth quad
                        else if ((diangleHit > 270) && (diangleHit < 360))
                        {
                            if (tank.vSpeed.X > 0)
                                tank.handleXCollision();
                            if (tank.vSpeed.Y > 0)
                                tank.handleYCollision();
                        }
                    }//If: Collisions==1 and it was a diangle hit

                }//foreach: Tank in dictionary
            }//If: dicTanks > 1
        }
    }
}